/*
 * Created by Jaren at 2021/12/13 13:52
 */
import 'dart:convert';
import 'dart:developer';
import 'dart:typed_data';

import 'package:binary/binary.dart';
import 'package:inmotion_protocol/base/base_factory.dart';
import 'package:inmotion_protocol/base/file/file_manager.dart';
import 'package:inmotion_protocol/base/protocol.dart';
import 'package:inmotion_protocol/base/vehicle_data.dart';
import 'package:inmotion_protocol/common/accessory_info.dart';
import 'package:inmotion_protocol/common/assistant_settings.dart';
import 'package:inmotion_protocol/common/device_info_model.dart';
import 'package:inmotion_protocol/common/exceptions.dart';
import 'package:inmotion_protocol/common/file.dart';
import 'package:inmotion_protocol/common/fw_update_manager.dart';
import 'package:inmotion_protocol/common/log_file_manager.dart';
import 'package:inmotion_protocol/common/media_file_upload_manager.dart';
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/common/response.dart';
import 'package:inmotion_protocol/common/riding_statistics_helper.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/features.dart';
import 'package:inmotion_protocol/inmotion_protocol.dart';
import 'package:inmotion_protocol/lorin/bean/base/bms_info.dart';
import 'package:inmotion_protocol/lorin/bean/base/real_time_info.dart';
import 'package:inmotion_protocol/lorin/bean/base/tbox.dart';
import 'package:inmotion_protocol/lorin/bean/base/tire_pressure_sensor.dart';
import 'package:inmotion_protocol/lorin/bean/common/bms_log_manager.dart';
import 'package:inmotion_protocol/lorin/bean/common/response/response.dart';
import 'package:inmotion_protocol/lorin/bean/common/bms_info.dart';
import 'package:inmotion_protocol/lorin/bean/euc/e10/e10_settings.dart';
import 'package:inmotion_protocol/lorin/bean/euc/e20/e20_settings.dart';
import 'package:inmotion_protocol/lorin/bean/euc/e25/e25_settings.dart';
import 'package:inmotion_protocol/lorin/bean/euc/euc_riding_statistics_helper.dart';
import 'package:inmotion_protocol/lorin/bean/euc/p6/p6_settings.dart';
import 'package:inmotion_protocol/lorin/bean/euc/v13/v13_settings.dart';
import 'package:inmotion_protocol/lorin/bean/euc/v18/v18_settings.dart';
import 'package:inmotion_protocol/lorin/constant.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/e10_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/e20_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/e25_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/euc_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/p6_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/v13_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/v18_message_factory.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_download_manager.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_manager.dart';
import 'package:inmotion_protocol/lorin/log_file_manager.dart';
import 'package:inmotion_protocol/lorin/media/avatar_file_manager.dart';
import 'package:inmotion_protocol/lorin/sound/sound_pack_file_upload_manager.dart';
import 'package:inmotion_protocol/lorin/bean/common/date.dart';
import 'package:inmotion_protocol/lorin/bean/euc/v11/v11_settings.dart';
import 'package:inmotion_protocol/lorin/bean/euc/v12/v12_settings.dart';
import 'package:inmotion_protocol/lorin/codec.dart';
import 'package:inmotion_protocol/lorin/factory/lorin_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/v11_message_factory.dart';
import 'package:inmotion_protocol/lorin/factory/special/euc/v12_message_factory.dart';
import 'package:inmotion_protocol/lorin/file/browse_file_method.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file.dart';
import 'package:inmotion_protocol/lorin/file/lorin_file_upload_manager.dart';
import 'package:inmotion_protocol/lorin/file/response.dart';
import 'package:inmotion_protocol/lorin/file/storage_info.dart';
import 'package:inmotion_protocol/lorin/fw_update_manager.dart';
import 'package:inmotion_protocol/lorin/lighteffect/light_effect_file_upload_manager.dart';
import 'package:inmotion_protocol/lorin/lorin_message.dart';
import 'package:inmotion_protocol/lorin/special/parser.dart';
import 'package:inmotion_protocol/lorin/util.dart';
import 'package:inmotion_protocol/protocol_worker.dart';
import 'package:inmotion_protocol/util/aes.dart';
import 'package:inmotion_protocol/util/byte_util.dart';
import 'package:inmotion_protocol/util/device.dart';
import 'package:inmotion_protocol/util/file.dart';
import 'package:inmotion_protocol/util/log.dart';
import 'package:inmotion_protocol/util/version.dart';
import 'package:inmotion_protocol/lorin/bean/scooter/scooter_settings.dart';

import 'bean/euc/v6/v6_settings.dart';
import 'factory/general/general_message.factory.dart';
import 'factory/special/euc/v6_message_factory.dart';

class ProtocolGlobal {
  static bool isBleSend = true;
}

/// The implement of 'Lorin Protocol'
class LorinProtocol extends Protocol<LorinMessage> {
  /// The specific parser, will be instanced when the [setup] is called.
  Parser? _parser;

  LorinComposer? _composer;

  // 正在请求升级设备的设备号
  int? deviceRequestingUpdate;

  LorinProtocol(ProtocolWorker<LorinMessage> protocolWorker,
      MsgFactory<LorinMessage> msgFactory)
      : super(protocolWorker, msgFactory);

  /// instance the message factory and the [_parser] by given [model] and [version]
  @override
  void setup(ProductModel model, VersionWrapper version) {
    productProperty.model = model;
    productProperty.versionWrapper = version;
    ProductProperty.setDefaultProperty(productProperty);
    msgFactory().init(productProperty);
    deviceRequestingUpdate = null;
    if (model.isV11Series()) {
      _parser = V11Parser(model, version);
      _composer = V11Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isV12Series()) {
      _parser = V12Parser(model, version);
      _composer = V12Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isV13Series()) {
      _parser = V13Parser(model, version);
      _composer = V13Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isV14Series()) {
      _parser = V14Parser(model, version);
      _composer = V14Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isE20Series()) {
      _parser = E20Parser(model, version);
      _composer = E20Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isE10Series() || model.isE15Series()) {
      _parser = E10Parser(model, version);
      _composer = E10Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isP6Series()) {
      _parser = P6Parser(model, version);
      _composer =
          P6Composer(protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isV6Series()) {
      _parser = V6Parser(model, version);
      _composer =
          V6Composer(protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isV9Series()) {
      _parser = E25Parser(model, version);
      _composer = E25Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isV12sSeries()) {
      _parser = V18Parser(model, version);
      _composer = V18Composer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isLS1Series()) {
      _parser = S1Parser(model, version);
      _composer = LorinComposer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isLA1Series()) {
      _parser = A1Parser(model, version);
      _composer = LorinComposer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isLC1Series()) {
      _parser = C1Parser(model, version);
      _composer = LorinComposer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isLE1Series()) {
      _parser = LE1Parser(model, version);
      _composer = LorinComposer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
    } else if (model.isLR1Series()) {
      _parser = LR1Parser(model, version);
      _composer = LorinComposer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
      protocolWorker().defaultTimeoutMs = 800;
    } else if (model.isRSVeloSeries()) {
      _parser = RsVeloParser(model, version);
      _composer = LorinComposer(
          protocolWorker(), msgFactory(), productProperty, _parser!);
      protocolWorker().defaultTimeoutMs = 800;
    } else {
      throw InitException("The model [$model] is not supported!");
    }
  }

  @override
  LorinMessageFactory msgFactory() {
    return super.msgFactory() as LorinMessageFactory;
  }

  @override
  void setUnhandledMsgHandler(Function f) {
    super.setUnhandledMsgHandler((msg) {
      int? device = Util.whichDeviceRequestingUpdate(msg);
      if (device != null) deviceRequestingUpdate = device;
      return f(msg);
    });
  }

  @override
  Future<ProductProperty> requestProductPropertyV2() {
    return Future.delayed(const Duration(milliseconds: 1000), () {
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genRequestDeviceInfoMsg(),
          timeoutMs: 500, maxRetryTimes: 5)
          .then((value) {
        Uint8ClampedList para = (value.data as LorinSpecialMessageData).para!;
        VehicleProductInfo productInfo = VehicleProductInfo.fromBytes(para);

        ProductModel model = ProductModel(
          productInfo.productFeature.mainSeries,
          productInfo.productFeature.subSeries,
          productInfo.productFeature.model,
          productInfo.productFeature.batch,
          productInfo.interfaceVersion,
          Uint8.zero,
        );

        DateTime activatedTime = productInfo.activationDate.toDateTime();

        VersionWrapper versionWrapper = productInfo.versionWrapper;

        log("✅✅✅requestProductProperty✅✅sn = ${productInfo.sn.replaceAll('\x00', '')} , model = $model, activatedTime = $activatedTime, versionWrapper = ${versionWrapper.toString()}");

        return ProductProperty(
            productInfo.sn.replaceAll('\x00', ''), model, activatedTime, versionWrapper);
      }).catchError((error) {
        if (error is DeviceRequestingUpdateException) throw error;
        if (error is RequestProductPropertyFailedException) throw error;
        if (error is MsgTimeoutException) {
          throw RequestProductPropertyFailedException.byDeviceInfoTimeout();
        }
        throw RequestProductPropertyFailedException.byDeviceInfoParseFailed();
      });

    });
  }

  @override
  Future<ProductProperty> requestProductProperty() {
    /// SN
    return Future.delayed(const Duration(milliseconds: 1000), () {
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genRequestSnMsg(),
              timeoutMs: 500, maxRetryTimes: 5)
          .then((value) {
        String sn = Util.parseSn((value.data as LorinGeneralMessageData).para);
        print("✅✅✅requestProductProperty✅✅ sn = $sn");

        /// 产品型号
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genRequestModelMsg(), maxRetryTimes: 3)
            .then((value) {
          ProductModel model =
              Util.parseModel((value.data as LorinGeneralMessageData).para);
          print("✅✅✅requestProductProperty✅✅ model = $model");

          /// 软件版本号
          return protocolWorker()
              .sendAndGetRsp(msgFactory().genRequestVersionMsg(),
                  maxRetryTimes: 3)
              .then((value) {
            VersionWrapper versionWrapper = Util.parseFwVersion(
                (value.data as LorinGeneralMessageData).para);
            print(
                "✅✅✅requestProductProperty✅✅ versionWrapper = ${versionWrapper.toString()}");

            /// 检查设备是否正在请求升级
            if (deviceRequestingUpdate != null) {
              throw DeviceRequestingUpdateException(
                  deviceRequestingUpdate!, sn, model, versionWrapper);
            }

            /// 激活时间
            return protocolWorker()
                .sendAndGetRsp(
                    LorinGeneralMessageFactory.genGetActivateDateMsg(),
                    maxRetryTimes: 3)
                .then((value) {
              Datetime activatedTime =
                  Util.parseDate(value.data as LorinGeneralMessageData);
              print(
                  "✅✅✅requestProductProperty✅✅ activatedTime = ${activatedTime.toString()}");

              /// 硬件版本号
              if (InMotionProtocol.isFeatureSupported(
                      Feature.hwVersion, model, versionWrapper) !=
                  1) {
                /// 不支持硬件版本号
                return Future.value(ProductProperty(
                    sn, model, activatedTime.toDateTime(), versionWrapper));
              }

              /// 继续获取硬件版本号
              return protocolWorker()
                  .sendAndGetRsp(
                      LorinGeneralMessageFactory.genGetHwVersionMsg(),
                      maxRetryTimes: 3)
                  .then((value) {
                versionWrapper = Util.parseHwVersion(
                    (value.data as LorinGeneralMessageData).para,
                    output: versionWrapper);

                print(
                    "✅✅✅requestProductProperty✅✅ versionWrapper = ${versionWrapper.toString()}");
                return ProductProperty(
                    sn, model, activatedTime.toDateTime(), versionWrapper);
              }).catchError((error) {
                if (error is RequestProductPropertyFailedException) throw error;
                if (error is MsgTimeoutException) {
                  throw RequestProductPropertyFailedException
                      .byHardwareVersionTimeout();
                }
                throw RequestProductPropertyFailedException
                    .byHardwareVersionParseFailed();
              });
            }).catchError((error) {
              if (error is RequestProductPropertyFailedException) throw error;
              if (error is MsgTimeoutException) {
                throw RequestProductPropertyFailedException
                    .bySoftwareVersionTimeout();
              }
              throw RequestProductPropertyFailedException
                  .bySoftwareVersionParseFailed();
            });
          }).catchError((error) {
            if (error is DeviceRequestingUpdateException) throw error;
            if (error is RequestProductPropertyFailedException) throw error;
            if (error is MsgTimeoutException) {
              throw RequestProductPropertyFailedException
                  .byActivatedTimeTimeout();
            }
            throw RequestProductPropertyFailedException
                .byActivatedTimeParseFailed();
          });
        }).catchError((error) {
          if (error is DeviceRequestingUpdateException) throw error;
          if (error is RequestProductPropertyFailedException) throw error;
          if (error is MsgTimeoutException) {
            throw RequestProductPropertyFailedException.byModelTimeout();
          }
          throw RequestProductPropertyFailedException.byModelParseFailed();
        });
      }).catchError((error) {
        if (error is DeviceRequestingUpdateException) throw error;
        if (error is RequestProductPropertyFailedException) throw error;
        if (error is MsgTimeoutException) {
          throw RequestProductPropertyFailedException.bySNTimeout();
        }
        throw RequestProductPropertyFailedException.bySNParseFailed();
      });
    });
  }

  @override
  Future<VehicleSynthesizeRealTimeInfo> requestVehicleSynthesizeRealTimeInfo() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestVehicleSynthesizeRealTimeInfoMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseVehicleSynthesizeRealTimeInfo(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<List<EsimModel>> requestTBoxEsimList() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestTBoxEsimListMsg())
        .then((rspMsg) {
      var rspBytes = (rspMsg.data as LorinSpecialMessageData).para!;
      return Util.parseTBoxEsimList(rspBytes);
    });
  }

  @override
  Future<TBoxInfo> requestTBoxRealTimeInfo() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestTBoxRealTimeInfoMsg())
        .then((rspMsg) {
      var rspBytes = (rspMsg.data as LorinSpecialMessageData).para!;
      return Util.parseTBoxRealTimeInfo(rspBytes);
    });
  }

  @override
  Future<bool> rebootTBox(int mode) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRebootTBoxMsg(mode))
        .then((rspMsg) {
      var rspBytes = (rspMsg.data as LorinSpecialMessageData).para!;
      if (rspBytes.isNotEmpty && rspBytes[0] == 0) return true;
      return false;
    });
  }

  @override
  Future<TBoxInfo> requestTBoxInfo() {
    TBoxInfo tBoxInfo = TBoxInfo();
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestTBoxInfoMsg())
        .then((rspMsg) {
      tBoxInfo.imei = Util.parseTBoxInfoByIMEI(
          (rspMsg.data as LorinSpecialMessageData).para);
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genRequestTBoxDeviceIdMsg());
    }).then((rspMsg) {
      tBoxInfo.deviceId = Util.parseTBoxDeviceIdByGeneralMessage(
          (rspMsg.data as LorinGeneralMessageData).para);
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genRequestTBoxUserInfoMsg());
    }).then((rspMsg) {
      List<String> list =
          Util.parseTBoxUserInfo((rspMsg.data as LorinSpecialMessageData).para);
      tBoxInfo.userName = list[0];
      tBoxInfo.pwd = list[1];
      return Future(() => tBoxInfo);
    });
  }

  // 绑定胎压传感器
  @override
  Future<bool> bindTirePressureSensor(
      String sensorId) {
    if(sensorId.isEmpty) {
      throw Exception("Sensor ID cannot be empty!");
    }

    if(sensorId.length == 6){
      // 如果是6位的ID，补齐为8位
      sensorId = '${sensorId}00';
    } else if (sensorId.length != 8) {
      throw Exception("Sensor ID must be 6 or 8 characters long!");
    }

    Uint8ClampedList bytes = ByteUtil.hexString2Bytes(sensorId);

    print("Binding Tire Pressure Sensor with ID: $sensorId, bytes: ${bytes.toString()},");
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genBindingTirePressureSensor(bytes))
        .then((rspMsg) {
      return (rspMsg.data as LorinGeneralMessageData).para != null;
    });
  }

  /// 设置胎压报警开关
  @override
  Future<SettingsResponse> tirePressureWarningOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genTirePressureWarningOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 设置胎压传感器低压报警阈值
  @override
  Future<SettingsResponse> setLowTirePressureWarningThreshold(
      int threshold) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genSetLowTirePressureWarningThresholdMsg(threshold))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 设置LOGO灯亮度
  @override
  Future<SettingsResponse> setLogoLightBrightness(int brightness) {
    if (brightness < 0 || brightness > 100) {
      throw Exception("Brightness must be between 0 and 100!");
    }
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetLogoLightBrightnessMsg(brightness))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 设置转向灯模式
  @override
  Future<SettingsResponse> setTurnSignalMode(int mode) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetTurnSignalModeMsg(mode))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 设置赛道倾斜角度
  @override
  Future<SettingsResponse> setBermAngle(int angle) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetBermAngleMsg(angle))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 设置输出饱和阈值
  @override
  Future<SettingsResponse> setOutputThreshold(int tiltBack, int warning1, warning2) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetOutputThresholdMsg(tiltBack, warning1, warning2))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }


  @override
  Future<VersionWrapper> requestFwVersion([int? target]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestVersionMsg(null, target))
        .then((value) => Util.parseFwVersion(
              msgFactory().isUpdateBMS(target)
                  ? (value.data as LorinSpecialMessageData).para
                  : (value.data as LorinGeneralMessageData).para,
              target,
              msgFactory().isUpdateBMS(target),
            ));
  }

  Future<String> requestProductSn() {
    return protocolWorker().sendAndGetRsp(msgFactory().genRequestSnMsg()).then(
        (rspMsg) =>
            Util.parseSn((rspMsg.data as LorinGeneralMessageData).para));
  }

  Future<ProductModel> requestProductModel() {
    return protocolWorker().sendAndGetRsp(msgFactory().genRequestSnMsg()).then(
        (rspMsg) =>
            Util.parseModel((rspMsg.data as LorinGeneralMessageData).para));
  }

  @override
  Future<AccessoryWrapper> requestAccessoriesInfo() {
    return protocolWorker()
        .sendAndGetRsp(LorinGeneralMessageFactory.genGetMotorSnMsg())
        .then((rspMsg) {
      AccessoryWrapper accessoryWrapper = Util.parseAccessories(
          Accessory.motor, (rspMsg.data as LorinGeneralMessageData).para!);
      return protocolWorker()
          .sendAndGetRsp(LorinGeneralMessageFactory.genGetBatterySnMsg())
          .then((rspMsg) {
        accessoryWrapper = Util.parseAccessories(
            Accessory.battery, (rspMsg.data as LorinGeneralMessageData).para!,
            output: accessoryWrapper);
        return accessoryWrapper;
      });
    });
  }

  @override
  Future<AllRealTimeData> requestAllRealTimeData() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestAllRealTimeDataMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseAllRealTimeData((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<RealTimeInfo> requestRealTimeInfo() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestRealTimeInfoMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseRealTimeInfo((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<RealTimeState> requestRealTimeState() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestRealTimeStateMsg(),
            maxRetryTimes: 3)
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseRealTimeState((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<RealTimeError> requestRealTimeError() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestRealTimeErrorMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseRealTimeError((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<AbsBatteryRealTimeInfo> requestBatteryRealTimeInfo() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBatteryRealTimeMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseBatteryRealTimeInfo(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<Settings> requestSettings() {
    return _composer!.requestSettings();
  }

  @override
  Future<void> respondQuickConnect() {
    throw UnimplementedError();
  }

  @override
  Future<DateTime> requestActivatedTime() {
    return protocolWorker()
        .sendAndGetRsp(LorinGeneralMessageFactory.genGetActivateDateMsg())
        .then((rspMsg) => Util.parseDate(rspMsg.data as LorinGeneralMessageData)
            .toDateTime());
  }

  @override
  Future<DeviceWrapper> requestDevicesId(List<int> devices) {
    if (devices.isEmpty) return Future.value(DeviceWrapper());
    Iterator<int> iterator = devices.iterator;
    iterator.moveNext();
    return _requestDevicesId(DeviceWrapper(), iterator);
  }

  /// 递归查询设备唯一ID
  Future<DeviceWrapper> _requestDevicesId(
      DeviceWrapper deviceWrapper, Iterator<int> iterator) {
    int device = iterator.current;
    return protocolWorker()
        .sendAndGetRsp(LorinGeneralMessageFactory.genGetIdentifierMsg(device))
        .then((rspData) {
      String deviceId =
          Util.parseDeviceId((rspData.data as LorinGeneralMessageData).para!);
      deviceWrapper.devices[device] = Device(device, deviceId);
      if (iterator.moveNext()) {
        return _requestDevicesId(deviceWrapper, iterator);
      }
      return deviceWrapper;
    }, onError: (Object e) {
      if (e is MsgTimeoutException) {
        deviceWrapper.devices[device] = Device(device, "");
        return deviceWrapper;
      }
      throw e;
    });
  }

  @override
  Future<Uint8ClampedList> requestLightEffectMode() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestLightEffectMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return (rspMsg.data as LorinSpecialMessageData).para!;
    });
  }

  @override
  Future<bool> syncRTC(DateTime? dateTime) {
    if (msgFactory().specialMessageFactory is! EucLorinSpecialMessageFactory) {
      return Future(() => true);
    }
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSyncRTCMsg(dateTime))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseSettingsResponse((rspMsg.data as LorinSpecialMessageData).para!)
          .isSuccess();
    });
  }

  void checkSpecialRspParam(LorinMessage rspMsg) {
    if ((rspMsg.data as LorinSpecialMessageData).para == null) {
      throw ProtocolParseException("Param is null!");
    }
  }

  void checkGeneralRspParam(LorinMessage rspMsg) {
    if ((rspMsg.data as LorinGeneralMessageData).para == null) {
      throw ProtocolParseException("Param is null!");
    }
  }

  @override
  Future<SettingsResponse> lostMode([bool enable = true]) {
    int target = DeviceUtils.getHmicDevice(productProperty.model);
    var msg = enable
        ? LorinGeneralMessageFactory.genEnableLostModeMsg(target, 2)
        : LorinGeneralMessageFactory.genDisableLostModeMsg(target);

    return protocolWorker().sendAndGetRsp(msg).then((rspMsg) {
      checkGeneralRspParam(rspMsg);

      return GeneralCtrlResponse(
          GeneralCtrlResponse.compactError(
              (rspMsg.data as LorinGeneralMessageData).para![0]),
          productProperty.model,
          productProperty.versionWrapper);
    });
  }

  @override
  Future<bool> activate(DateTime dateTime) {
    int target = DeviceUtils.getHmicDevice(productProperty.model);
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genActivateMsg(target, dateTime))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      var rspBytes = (rspMsg.data as LorinGeneralMessageData).para!;
      if (rspBytes.isNotEmpty && rspBytes[0] == 0) return true;
      return false;
    });
  }

  @override
  Future<SettingsResponse> autoHeadlightOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genAutoHeadlightOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> autoScreenOffOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genAutoScreenOffOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startAccHandleCalibration() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory()
            .genStartScooterCalibrationMsg(Constant.calibrationAccHandle))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startBrakeHandleCalibration() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory()
            .genStartScooterCalibrationMsg(Constant.calibrationBrakeHandle))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startBalanceCalibration() {
    // 平衡校准需校准陀螺仪零点和俯仰角零点
    return protocolWorker()
        .sendAndGetRsp(msgFactory()
            .genStartIMUCalibrationMsg(type0: 1, type1: 1, type2: 0))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startTurningCalibration() {
    // 转弯前倾校准需校准陀螺仪零点和翻滚角零点
    return protocolWorker()
        .sendAndGetRsp(msgFactory()
            .genStartIMUCalibrationMsg(type0: 1, type1: 0, type2: 1))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<AbsCalibrationResultResponse> queryIMUCalibrationResult() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genQueryIMUCalibrationResultMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseCalibrationResultResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startCalibration(int which) {
    switch (which) {
      case Constant.calibrationAccHandle:
      case Constant.calibrationBrakeHandle:
      case Constant.calibrationScooterIMUHandle:
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genStartScooterCalibrationMsg(which))
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          return __parser().parseSettingsResponse(
              (rspMsg.data as LorinSpecialMessageData).para!);
        });
      case Constant.calibrationBalance:
      case Constant.calibrationTurning:

        /// EUC平衡校准
        /// EUC转弯前倾校准
        int type0, type1, type2 = 0;
        if (which == Constant.calibrationBalance) {
          type0 = 1;
          type1 = 1;
          type2 = 0;
        } else {
          type0 = 1;
          type1 = 0;
          type2 = 1;
        }
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genStartIMUCalibrationMsg(
                type0: type0, type1: type1, type2: type2))
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          Uint8ClampedList param =
              (rspMsg.data as LorinSpecialMessageData).para!;
          if (which == Constant.calibrationBalance) {
            // 平衡角度校准
            if (param[0] == 0 && param[1] == 0) {
              return SettingsResponse.success();
            }
            if (param[0] == 5 && param[1] == 5) {
              return SettingsResponse.notNow();
            }
            return SettingsResponse.unknown();
          }
          // 转弯前倾校正结果
          if (param[0] == 0 && param[2] == 0) return SettingsResponse.success();
          if (param[0] == 5 && param[1] == 5) return SettingsResponse.notNow();
          return SettingsResponse.unknown();
        });
      case Constant.calibrationBatteryVoltage:

        /// 电池电压校准
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genStartBatteryCalibrationMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          if ((rspMsg.data as LorinSpecialMessageData).para![0] == 1) {
            return SettingsResponse.success();
          }
          return SettingsResponse.unknown();
        });
      case Constant.calibrationMotorAutoCompat:

        /// 电机自适应
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genStartMotorAutoCalibrationMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          if ((rspMsg.data as LorinSpecialMessageData).para![0] == 1) {
            return SettingsResponse.success();
          }
          return SettingsResponse.unknown();
        });
      case Constant.calibrationMotorSelfCheck:

        /// 电机自检
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genStartMotorSelfCheckMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          if ((rspMsg.data as LorinSpecialMessageData).para![0] == 1) {
            return SettingsResponse.success();
          }
          return SettingsResponse.unknown();
        });
    }
    throw NotSupportException("Unknown which param [$which].");
  }

  @override
  Future<AbsCalibrationResultResponse> queryCalibrationResult(int which) {
    switch (which) {
      case Constant.calibrationAccHandle:
      case Constant.calibrationBrakeHandle:
      case Constant.calibrationScooterIMUHandle:
        return protocolWorker()
            .sendAndGetRsp(
                msgFactory().genQueryScooterCalibrationResultMsg(which))
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          return __parser().parseCalibrationResultResponse(
              (rspMsg.data as LorinSpecialMessageData).para!);
        });

      case Constant.calibrationBalance:
      case Constant.calibrationTurning:
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genQueryIMUCalibrationResultMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          return __parser().parseCalibrationResultResponse(
              (rspMsg.data as LorinSpecialMessageData).para!);
        });
      case Constant.calibrationBatteryVoltage:

        /// 电池电压校准
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genQueryBatteryCalibrationResultMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          return BatteryCalibrationResultResponse.fromBytes(
              (rspMsg.data as LorinSpecialMessageData).para!);
        });
      case Constant.calibrationMotorAutoCompat:

        /// 电机自适应
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genQueryMotorAutoCalibrationResultMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          return MotorAutoCalibrateResultResponse.fromBytes(
              (rspMsg.data as LorinSpecialMessageData).para!);
        });
      case Constant.calibrationMotorSelfCheck:

        /// 电机自检
        return protocolWorker()
            .sendAndGetRsp(msgFactory().genQueryMotorSelfCheckResultMsg())
            .then((rspMsg) {
          checkSpecialRspParam(rspMsg);
          return MotorSelfCheckResultResponse.fromBytes(
              (rspMsg.data as LorinSpecialMessageData).para!);
        });
    }
    throw NotSupportException("Unknown which param [$which].");
  }

  @override
  Future<SettingsResponse> cruiseOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genCruiseOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> fanOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genFanOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> fanQuietModeOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genFanQuietModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> hacOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genHacOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> hdcOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genHdcOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> headlightOnOff(
      {bool? on, bool? lowBeamOn, bool? highBeamOn}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genHeadlightOnOffMsg(
            on: on, lowBeamOn: lowBeamOn, highBeamOn: highBeamOn))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> loadDetectOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genLoadDetectOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> lock([bool lock = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genLockMsg(lock), maxRetryTimes: 2)
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> lowBatLevelProtectionModeOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genLowBatteryProtectionModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> tboxLowBatLevelWakeUpVehicleModeOnOff(
      [bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genTboxLowBatLevelWakeUpVehicleModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> showTboxInfoOnVehicleOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genShowTboxInfoOnVehicleOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> noLoadDetectOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genNoLoadDetectOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<AbsCalibrationResultResponse> queryHandleCalibrationResult(
      [int which = 0]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genQueryScooterCalibrationResultMsg(which))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseCalibrationResultResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> remainderRangeEstimateOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRemainderRangeEstimateOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> safeSpeedLimitOnOff([bool on = true]) {
    if (productProperty.model.isScooter()) {
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genSafeSpeedLimitOnOffMsg(on))
          .then((rspMsg) {
        checkSpecialRspParam(rspMsg);
        return __parser().parseSettingsResponse(
            (rspMsg.data as LorinSpecialMessageData).para!);
      });
    }
    // EUC车型，此功能名称为：解除安全限速，所以on和off需要手动反一下
    on = !on;
    return buildSecurityConnection().then((success) {
      if (!success) return SettingsResponse.unknown();
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genSafeSpeedLimitOnOffMsg(on))
          .then((rspMsg) {
        checkSpecialRspParam(rspMsg);
        return __parser().parseSettingsResponse(
            (rspMsg.data as LorinSpecialMessageData).para!);
      });
    });
  }

  @override
  Future<SettingsResponse> bermAngleModeOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genBermAngleModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> autoLowHighBeamOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genAutoLowHighBeamOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setAutoHeadlightBrightnessThr(
      int lowThr, int highThr) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genSetAutoHeadlightBrightnessThrMsg(lowThr, highThr))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setHeadlightBrightness(
      {int? brightness, int? lowBeamBrightness, int? highBeamBrightness}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetHeadlightBrightnessMsg(
            brightness: brightness,
            lowBeamBrightness: lowBeamBrightness,
            highBeamBrightness: highBeamBrightness))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setDeviceName(String name) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetDeviceNameMsg(name))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> requestDeviceName() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestDeviceNameMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setDriveMode(int mode) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetDriveModeMsg(mode))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setLightEffectId(int id, [int? color]) {
    /// 忽略[color]参数
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetLightEffectIdMsg(id))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setPassword(String pwd, [int? type]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetPasswordMsg(pwd, type!))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setPasswordType(int type) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetPasswordTypeMsg(type))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setPedalSensitivity(int sensitivity,
      [int? sensitivity2]) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genSetPedalSensitivityMsg(sensitivity, sensitivity2))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setPitchAngleZero(int angle) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetPitchAngleZeroMsg(angle))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setRidingMode(int mode, [var param]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetRidingModeMsg(mode))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setAssistantMode(int mode, [var param]) {
    throw UnimplementedError();
  }

  @override
  Future<SettingsResponse> setSoundPackId(int id) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetSoundPackIdMsg(id))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setSoundWaveSensitivity(int sensitivity) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetSoundWaveSensitivityMsg(sensitivity))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setSpeedLimit(int speedLimit, [int? speedLimit2]) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genSetSpeedLimitMsg(speedLimit, speedLimit2))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setSpeedLimitOfAssistMode(int speedLimit) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetSpeedLimitOfAssistModeMsg(speedLimit))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setAutoLowHighBeamSwitchSpeedThr(int speedThr) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genSetAutoLowHighBeamSwitchSpeedThrMsg(speedThr))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setSpeedingBrakingSensitivity(
      int speeding, int braking) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genSetSpeedingBrakingSensitivityMsg(speeding, braking))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setStandbyTime(int seconds) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetStandbyTimeMsg(seconds))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setVolume(int volume) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetVolumeMsg(volume))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> soundPackOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSoundPackOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> soundWaveOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSoundWaveOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> speedingBrakingOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSpeedingBrakingOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> overSpeedWarningOnOff([bool on = true]) {
    throw UnimplementedError();
  }

  @override
  Future<SettingsResponse> spinKillOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSpinKillOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> transportationModeOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genTransportationModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> usbPowerOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genUsbPowerOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> zeroSpeedupOnOff(
      [bool on = true, AbsAssistanceSettings? assistanceSettings]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genZeroSpeedupOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> playSoundItem(int index) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genPlaySoundItemMsg(index + 1))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> horn() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genPlaySoundItemMsg(24))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<HistoryStatistics> requestCurrentStatistics() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestHistoryStatisticsMsg(0, 1))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSingleHistoryStatistics(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<StatisticsResponse> requestHistoryStatistics(
      [int index = 0, int count = 1]) {
    return protocolWorker()
        .sendAndGetRsp(
            msgFactory().genRequestHistoryStatisticsMsg(index, count))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseHistoryStatistics(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<StatisticsInfoResponse> requestHistoryStatisticsInfo() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestHistoryStatisticsMsg(null, null))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseStatisticsInfo((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<TotalStatistics> requestTotalStatistics() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestTotalStatisticsMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseTotalStatistics((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setLightEffectMode(
      {bool? onOff, int? mode, int? paramColor, int? paramMode}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetLightEffectModeMsg(
            onOff: onOff,
            mode: mode,
            paramColor: paramColor,
            paramMode: paramMode))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<bool> buildSecurityConnection() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestEncryptedKeyMsg(),
            maxRetryTimes: 1)
        .then((rspMsg) {
      var data = rspMsg.data as LorinGeneralMessageData;
      if (data.para == null) {
        throw ProtocolParseException('Invalid response of step#1.');
      }
      Uint8ClampedList decryptKey =
          AesUtil.decryptEcbNoPadding(data.para!, Cryptor.sAesKey);

      return protocolWorker()
          .sendAndGetRsp(msgFactory().genVerifyCryptKeyMsg(decryptKey),
              maxRetryTimes: 1)
          .then((rspMsg) {
        var data = rspMsg.data as LorinGeneralMessageData;
        if (data.para == null || data.para!.isEmpty) {
          throw ProtocolParseException('');
        }
        if (data.para![0] != 1) throw SecurityConnectionFailedException();
        return Future.value(true);
      }).catchError((e) => throw e);
    });
  }

  @override
  FwUpdateManager createFwUpdateManager(LinkLayerDeviceHandler handler,
      RequiredManualOperationHandler requiredManualOperationHandler) {
    return LorinFwUpdateManager(this, handler, requiredManualOperationHandler);
  }

  Parser __parser() {
    if (_parser == null) {
      throw InitException(
          'Lorin special message parser is not setup, maybe the target PRODUCT MODEL is not supported!');
    }
    return _parser!;
  }

  @override
  Future<CheckFileResponse> checkFile(
      {int? target,
      int? fileHandle,
      int? offset,
      int? length,
      Uint8ClampedList? check}) {
    if (fileHandle == null ||
        offset == null ||
        length == null ||
        check == null) {
      throw InvalidParamException(
          'Param [fileHandle] and [offset] could not be null.');
    }
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genCheckFileMsg(
                fileHandle, length, offset, check, target),
            timeoutMs: 7000)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return CheckFileResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<FileResponse> getFileCheck(
      {int? target, int? fileHandle, int? offset}) {
    if (fileHandle == null || offset == null) {
      throw InvalidParamException(
          'Param [fileHandle] and [offset] could not be null.');
    }
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genGetFileCheckMsg(
                fileHandle, offset, target),
            timeoutMs: 7000)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return GetFileCheckResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<FileResponse> closeFile({int? target, int? fileHandle}) {
    if (fileHandle == null) {
      throw InvalidParamException(
          'Param [target] and [fileHandle] could not be null.');
    }
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genCloseFileMsg(fileHandle, target))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return LorinFileResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<OpenFileResponse> openFile(
      {int? target, int? openType, String? name, int? type, int? tag}) {
    if (openType == null || name == null) {
      throw InvalidParamException(
          'Param [openType] and [name] could not be null.');
    }
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genOpenFileMsg(name, openType, target),
            timeoutMs: 7000)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return OpenFileResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<FileResponse> setFileOffset({int? type, int? offset}) {
    throw UnimplementedError();
  }

  @override
  Future<WriteFileResponse> writeFile(Uint8ClampedList content,
      {int? tab,
      int? target,
      int? fileHandle,
      int? offset,
      int? contentLength}) {
    if (fileHandle == null || offset == null) {
      throw InvalidParamException(
          'Param [fileHandle] and [offset] could not be null.');
    }
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genWriteFileMsg(
                fileHandle, offset, content, tab, target),
            timeoutMs: 500,
            maxRetryTimes: 5)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return WriteFileResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<ReadFileResponse> getFile(
      {int? tab,
      int? target,
      int? fileHandle,
      int? offset,
      int? contentLength}) {
    if (fileHandle == null || offset == null || contentLength == null) {
      throw InvalidParamException(
          'Param [fileHandle], [offset] and [contentLength] could not be null.');
    }
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genGetFileMsg(
                fileHandle, offset, contentLength, tab, target),
            timeoutMs: 1000,
            maxRetryTimes: 3)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return ReadFileResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startUpdate(int target, {Uint8ClampedList? para}) {
    bool isScreen = target == Constant.deviceScreen;
    if (isScreen) {
      return protocolWorker()
          .sendAndGetRsp(msgFactory().genStartUpgradingFirmwareMsg(para),
              maxRetryTimes: 3)
          .then((rspMsg) {
        checkSpecialRspParam(rspMsg);
        return __parser().parseSettingsResponse(
            (rspMsg.data as LorinSpecialMessageData).para!);
      });
    } else {
      return protocolWorker()
          .sendAndGetRsp(
              LorinGeneralMessageFactory.genStartUpgradingFirmwareMsg(
                target,
                para,
              ),
              maxRetryTimes: 3)
          .then((rspMsg) {
        checkGeneralRspParam(rspMsg);
        return __parser().parseSettingsResponse(
            (rspMsg.data as LorinGeneralMessageData).para!);
      });
    }
  }

  @override
  Future<SettingsResponse> startTransfer(int target, {Uint8ClampedList? para}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genStartTransferFirmwareMsg(para),
            timeoutMs: 3000, maxRetryTimes: 3)
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
        (rspMsg.data as LorinSpecialMessageData).para!,
        0,
        true,
      );
    });
  }

  @override
  SoundFileUploadManager createSoundFileUploadManager() {
    LorinSoundFileUploadManager manager = LorinSoundFileUploadManager(this);
    return manager;
  }

  @override
  IFileManager createFileUploadManager(FileConfig config) {
    return LorinFileUploadManager(this, config as LorinFileManagerConfig);
  }

  @override
  LightEffectPkgFileUploadManager createLightEffectPkgUploadManager() {
    LorinLightEffectFileUploadManager manager =
        LorinLightEffectFileUploadManager(this);
    return manager;
  }

  @override
  AvatarFileManager createAvatarFileManager() {
    AvatarFileManager manager = AvatarFileManager(this);
    return manager;
  }

  @override
  Future<FileResponse> deleteFile(String path, {int? target}) {
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genDeleteFileMsg(path, target))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return LorinFileResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<List<int>> getSoundPackIdList({int? currentSoundPackId}) {
    return getFileList(
            index: 0,
            filter: BrowseFileMethodBuilder()
                .fileOnly()
                .depthCurrentDir()
                .fileType('rmf')
                .withPath('0:/audio')
                .build())
        .then((rsp) {
      if (!rsp.isSuccess()) return [];
      rsp.files;
      List<int> idList = [];
      for (File file in rsp.files) {
        file as LorinFile;
        if (file.isDirectory() || file.name == '') continue;
        String nameExcludeFileType = FileUtils.getFileNameNoFormat(file.name);
        if (!file.name.toUpperCase().endsWith("RMF")) {
          // 非有效音效文件
          continue;
        }
        if (file.getAbsolutePath().toUpperCase().startsWith("0:/AUDIO/DIY")) {
          // 过滤DIY目录下文件；屏蔽车辆端BUG（未实现遍历深度）
          continue;
        }
        if (nameExcludeFileType != '') {
          int? soundPackId = int.tryParse(nameExcludeFileType);
          if (soundPackId == null) continue;
          idList.add(soundPackId);
        }
      }
      return idList;
    });
  }

  @override
  Future<FileResponse> deleteDiySoundItem(int soundIndex) {
    return deleteFile("0:/audio/diy/${soundIndex + 1}.rmf");
  }

  @override
  Future<FileResponse> deleteSoundPack(int id) {
    return deleteFile("0:/audio/$id.rmf");
  }

  @override
  Future<FileResponse> deleteLightEffectPkg(int id) {
    return deleteFile("0:/light/diy/$id.rgb");
  }

  @override
  Future<FileListResponse> getFileList(
      {int index = 0, Object? filter, int? target}) {
    return protocolWorker()
        .sendAndGetRsp(LorinGeneralMessageFactory.genGetFileListMsg(
            index, (filter as BrowseFileMethod).generate(), target))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return LorinFileListResponse.fromBytes(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> writeForceUpdate(
      int level, String minVersion, String maxVersion) {
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genForceUpgradeMsg(
                DeviceUtils.getHmicDevice(productProperty.model),
                level,
                VersionUtils.fwVersionText2Bytes(minVersion),
                VersionUtils.fwVersionText2Bytes(maxVersion)),
            maxRetryTimes: 3)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinGeneralMessageData).para!);
    });
  }

  @override
  Future<FirmwareState> requestFirmwareState() {
    return protocolWorker()
        .sendAndGetRsp(LorinGeneralMessageFactory.genGetForceUpgradeStateMsg(
            DeviceUtils.getHmicDevice(productProperty.model)))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);

      Uint8ClampedList bytes = (rspMsg.data as LorinGeneralMessageData).para!;

      int offset = 0;
      int level = bytes[offset];
      if (level == 0) return FirmwareState.ok;
      offset++;
      String minVersion =
          Util.formatVersion(bytes, offset, Version.singleVersionLength);
      offset += Version.singleVersionLength;
      String maxVersion =
          Util.formatVersion(bytes, offset, Version.singleVersionLength);
      if (level == LorinFwUpdateManager.markAsUpdatingLevel &&
          LorinFwUpdateManager.markAsUpdatingVersion == minVersion &&
          LorinFwUpdateManager.markAsUpdatingVersion == maxVersion) {
        return FirmwareState.lastUpdateInterrupted;
      }
      return FirmwareState.needForceUpdate;
    });
  }

  @override
  Future<int> getRemainStorageCapacity({int diskIndex = 0}) {
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genStorageCapacityMsg(diskIndex))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      StorageInfo storageInfo =
          StorageInfo.fromBytes((rspMsg.data as LorinGeneralMessageData).para!);
      return storageInfo.remain;
    });
  }

  @override
  Future<FileResponse> renameFile(String filePath, String newFilePath) {
    return protocolWorker()
        .sendAndGetRsp(
            LorinGeneralMessageFactory.genRenameFileMsg(filePath, newFilePath))
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return FileResponse.byOriginError(
          (rspMsg.data as LorinGeneralMessageData).para![0]);
    });
  }

  @override
  Future<List<int>> getSoundItemIndexList({int index = 0, List<int>? output}) {
    return getSoundItemIndexList0(index: index, output: output).then((list) {
      for (var i = 0; i < list.length; i++) {
        list[i] -= 1;
      }
      return list;
    });
  }

  Future<List<int>> getSoundItemIndexList0({int index = 0, List<int>? output}) {
    output ??= [];
    return getFileList(
            index: index,
            filter: BrowseFileMethodBuilder()
                .fileOnly()
                .depthCurrentDir()
                .fileType('rmf')
                .withPath('0:/audio/diy')
                .build())
        .then((rsp) {
      if (!rsp.isSuccess()) return [];
      rsp.files;
      for (File file in rsp.files) {
        file as LorinFile;
        if (file.isDirectory() || file.name == '') continue;
        String nameExcludeFileType = FileUtils.getFileNameNoFormat(file.name);
        if (!file.name.toUpperCase().endsWith("RMF")) {
          // 非有效音效文件
          continue;
        }
        if (nameExcludeFileType != '') {
          int? soundPackId = int.tryParse(nameExcludeFileType);
          if (soundPackId == null) continue;
          output!.add(soundPackId);
        }
      }
      if (rsp.remain > 0) {
        return getSoundItemIndexList(index: index + 1, output: output);
      }
      return output!;
    });
  }

  @override
  Future<List<int>> getLightEffectPkgIdList(
      {int index = 0, List<int>? output}) {
    output ??= [];
    return getFileList(
            index: index,
            filter: BrowseFileMethodBuilder()
                .fileOnly()
                .depthCurrentDir()
                .fileType('rgb')
                .withPath('0:/light/diy')
                .build())
        .then((rsp) {
      if (!rsp.isSuccess()) return [];
      rsp.files;
      for (File file in rsp.files) {
        file as LorinFile;
        if (file.isDirectory() || file.name == '') continue;
        String nameExcludeFileType = FileUtils.getFileNameNoFormat(file.name);
        if (!file.name.toUpperCase().endsWith("RGB")) {
          // 非有效音效文件
          continue;
        }
        if (nameExcludeFileType != '') {
          int? id = int.tryParse(nameExcludeFileType);
          if (id == null) continue;
          output!.add(id);
        }
      }
      if (rsp.remain > 0) {
        return getLightEffectPkgIdList(index: index + 1, output: output);
      }
      return output!;
    });
  }

  @override
  Future<SettingsResponse> setSpeedUnit(int unit) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetSpeedUnitMsg(unit))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> daytimeRunningLightOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetDaytimeRunningLightMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<void> requestRebootHmic() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRebootRequestMsg(
          null,
          Constant.deviceEUCV11HMIC,
        ))
        .then((value) =>
            protocolWorker().sendAndGetRsp(msgFactory().genRebootConfirmMsg(
              null,
              Constant.deviceEUCV11HMIC,
            )));
  }

  @override
  Future<SettingsResponse> factoryReset({int level = 0}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genFactoryResetMsg(level: level),
            timeoutMs: 10000)
        .then((rspMsg) {
      checkGeneralRspParam(rspMsg);
      return GeneralCtrlResponse(
          GeneralCtrlResponse.compactError(
              (rspMsg.data as LorinGeneralMessageData).para![0]),
          productProperty.model,
          productProperty.versionWrapper);
    });
  }

  @override
  IFileManager createFileDownloadManager(FileConfig config) {
    return LorinFileDownloadManager(this, config as LorinFileManagerConfig);
  }

  @override
  LogFileManager createLogFileManager() {
    return LorinLogFileManager(this);
  }

  @override
  Future prepareOnLinkLayerConnected(String deviceName,
      {String clientId = '', bool resetData = true}) async {
    return Future(() async {
      await Future.delayed(const Duration(milliseconds: 50));
    });
  }

  @override
  Future<SettingsResponse> setMaxChargeLevel(int level) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetMaxChargeLevelMsg(level))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setMaxDcOutputLevel(int level) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetMaxDCOutputLevelMsg(level))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setUSBMode(int mode) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetUSBModeMsg(mode))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<AbsBMSCellsVoltage> requestBMSCellsVoltage(int target) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBMSCellsVoltageMsg(target))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseBMSCellsVoltage((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<Datetime> requestBMSDate(int which) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBMSDateMsg(which))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return Datetime.fromBytes((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<BMSFixedInfo> requestBMSFixedInfo(int which) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBMSFixedInfoMsg(which),
            timeoutMs: 500, maxRetryTimes: 2)
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser()
          .parseBMSFixedInfo((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<BMSAllRealTimeInfo> requestBMSRealTimeInfo(int which) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBMSRealTimeInfoMsg(which))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseBMSAllRealTimeInfo(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> assistBalanceOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genAssistBalanceOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> startMotorAutoCalibration(
      {int hallOffsetCorrect = 1, int hallSectorCorrect = 1}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genStartMotorAutoCalibrationMsg(
            hallOffsetCalibrate: hallOffsetCorrect,
            hallSectorCalibrate: hallSectorCorrect))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      var param = (rspMsg.data as LorinSpecialMessageData).para!;
      if (param[0] == 1) return SettingsResponse.success();
      return SettingsResponse.unknown();
    });
  }

  @override
  Future<AbsCalibrationResultResponse> queryMotorAutoCalibrationResult() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genQueryMotorAutoCalibrationResultMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return MotorAutoCalibrateResultResponse.fromBytes(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> resetMotorAutoCalibrationEffect(
      {int hallOffset = 1, int hallSector = 1}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genResetMotorAutoCalibrationEffectMsg(
            hallOffset: hallOffset, hallSector: hallSector))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      var param = (rspMsg.data as LorinSpecialMessageData).para!;
      if (param[0] == 1) return SettingsResponse.success();
      return SettingsResponse.unknown();
    });
  }

  @override
  Future<SettingsResponse> startBatteryCalibration() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genStartBatteryCalibrationMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      var param = (rspMsg.data as LorinSpecialMessageData).para!;
      if (param[0] == 1) return SettingsResponse.success();
      return SettingsResponse.unknown();
    });
  }

  @override
  Future<AbsCalibrationResultResponse> queryBatteryCalibrationResult() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genQueryBatteryCalibrationResultMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return BatteryCalibrationResultResponse.fromBytes(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> stopMotorSelfCheck() {
    // 操作相同
    return stopMotorAutoCalibration();
  }

  @override
  Future<MotorSelfCheckResultResponse> queryMotorSelfCheckResult() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genQueryMotorSelfCheckResultMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return MotorSelfCheckResultResponse.fromBytes(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 启动电机自检
  /// [mode] 自检等级, 0 - 严格的自检; 1 - 一般的自检
  @override
  Future<SettingsResponse> startMotorSelfCheck({int method = 1}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genStartMotorSelfCheckMsg(method: method))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      var param = (rspMsg.data as LorinSpecialMessageData).para!;
      if (param[0] == 1) return SettingsResponse.success();
      return SettingsResponse.unknown();
    });
  }

  @override
  Future<SettingsResponse> stopMotorAutoCalibration() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genStopMotorAutoCalibrationMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      var param = (rspMsg.data as LorinSpecialMessageData).para!;
      if (param[0] == 1) return SettingsResponse.success();
      return SettingsResponse.unknown();
    });
  }

  @override
  Future<SettingsResponse> disableChargeDangerAlert() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genDisableChargeDangerAlertMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setWarningLimitSpeed(int speed1, int speed2) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetWarningLimitSpeedMsg(speed1, speed2))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<List<TirePressureSensor>> searchTirePressureSensor() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSearchTirePressureSensorMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseTirePressureSensors(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> resetTirePressureSensorSearchResult() {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genResetTirePressureSensorSearchResultMsg())
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  RidingStatisticsHelper createRidingStatisticsHelper() {
    return EUCRidingStatisticsHelper(this);
  }

  Future<BMSLogResponse> requestBMSLog(int device, int index) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBMSLogMsg(device, index),
            maxRetryTimes: 10, timeoutMs: 300)
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      try {
        return BMSLogResponse.fromBytes(
            (rspMsg.data as LorinSpecialMessageData).para!);
      } catch (e) {
        throw ProtocolParseException(e.toString());
      }
    });
  }

  Future<int> requestBMSLogCount(int which) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genRequestBMSLogCountMsg(which),
            maxRetryTimes: 3)
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return ByteUtil.bytes2IntLe(
          (rspMsg.data as LorinSpecialMessageData).para!, 4, 4);
    });
  }

  @override
  LorinBmsLogManager createBMSLogManager() {
    return LorinBmsLogManager(this);
  }

  @override
  Future<SettingsResponse> brakeFirstModeOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genBrakeFirstModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> onePedalModeOnOff([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genOnePedalModeOnOffMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setParkTime(int seconds) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetParkTimeMsg(seconds))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setAccForce(int force, {int? type}) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genAccForceMsg(force, type: type))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setBrakeForce(int force, {int? type}) {
    if (productProperty.model.isLE1Series()) {
      return setFrontRearBrakeForce(force);
    }
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genBrakeForceMsg(force, type: type))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  /// 同时设置前后电机的刹车力度
  Future<SettingsResponse> setFrontRearBrakeForce(int force) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory()
            .genBrakeForceMsg(force, type: ScooterSettings.motorFront))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      var settingsRsp = __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
      if (!settingsRsp.isSuccess()) return settingsRsp;

      return protocolWorker()
          .sendAndGetRsp(msgFactory()
              .genBrakeForceMsg(force, type: ScooterSettings.motorRear))
          .then((rspMsg) {
        checkSpecialRspParam(rspMsg);
        return __parser().parseSettingsResponse(
            (rspMsg.data as LorinSpecialMessageData).para!);
      });
    });
  }

  @override
  Future<LorinMessage> sendTransparentData(LorinMessage msg) {
    return protocolWorker().sendAndGetRsp(msg);
  }

  @override
  Future<SettingsResponse> gpsOnOff([bool on = true]) {
    throw UnimplementedError();
  }

  @override
  Future<SettingsResponse> setLanguage(int language) {
    throw UnimplementedError();
  }

  @override
  Future<SettingsResponse> setTurningSensitivity(int sensitivity) {
    throw UnimplementedError();
  }

  @override
  Future<SettingsResponse> powerOnOff([bool on = true]) {
    throw UnimplementedError();
  }

  @override
  Future<SettingsResponse> twoBatteryMode([bool on = true]) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genTwoBatteryModeMsg(on))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return __parser().parseSettingsResponse(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setMaxChargeCurrent(int currentAc220, int currentAc110) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetMaxChargeCurrentMsg(currentAc220, currentAc110))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return SettingsResponse.fromBytes(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<SettingsResponse> setChargeLimitPercentage(int percentage) {
    return protocolWorker()
        .sendAndGetRsp(msgFactory().genSetChargeLimitMsg(percentage))
        .then((rspMsg) {
      checkSpecialRspParam(rspMsg);
      return SettingsResponse.fromBytes(
          (rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

}

class LorinComposer extends MethodComposer<LorinMessage, LorinMessageFactory> {
  final Parser _parser;

  LorinComposer(ProtocolWorker<LorinMessage> protocolWorker,
      MsgFactory msgFactory, ProductProperty property, this._parser)
      : super(protocolWorker, msgFactory, property);

  @override
  Future<AllRealTimeData> requestAllRealTimeInfo() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestAllRealTimeDataMsg())
        .then((rspMsg) {
      return _parser
          .parseAllRealTimeData((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      return _parser
          .parseSettings((rspMsg.data as LorinSpecialMessageData).para!);
    });
  }

  LorinMessageFactory _msgFactory() {
    return msgFactory as LorinMessageFactory;
  }
}

class V11Composer extends LorinComposer {
  V11Composer(ProtocolWorker<LorinMessage> protocolWorker,
      MsgFactory msgFactory, ProductProperty property, Parser parser)
      : super(protocolWorker, msgFactory, property, parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      V11Settings v11settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as V11Settings;

      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as V11MessageFactory)
                  .genRequestFanManualStateMsg())
          .then((rspMsg) {
        v11settings.fanState =
            ByteUtil.toUint4((rspMsg.data as LorinSpecialMessageData).para![0]);
        return v11settings;
      });
    });
  }
}

class V12Composer extends LorinComposer {
  V12Composer(ProtocolWorker<LorinMessage> protocolWorker,
      MsgFactory msgFactory, ProductProperty property, Parser parser)
      : super(protocolWorker, msgFactory, property, parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      V12Settings v12settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as V12Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as V12MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        v12settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (v12settings.lightEffectMode.value ==
            V12Settings.lightEffectModeByMusic) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          v12settings.colorOfLightEffectByMusic = color;
        } else if (v12settings.lightEffectMode.value ==
            V12Settings.lightEffectModeBySpeed) {
          if (param.length > 4) {
            v12settings.styleOfLightEffectBySpeed = ByteUtil.toUint8(param[4]);
          }
        }

        /// 从综合设置信息中拿到的灯效包ID不正确，需要单独获取灯效包ID
        // 获取当前灯效包ID
        return protocolWorker
            .sendAndGetRsp(
                (_msgFactory().specialMessageFactory as V12MessageFactory)
                    .genRequestCurrentLightEffectIdMsg())
            .then((rspMsg) {
          v12settings.lightEffectId = ByteUtil.bytes2Uint32Le(
              (rspMsg.data as LorinSpecialMessageData).para!, 0);

          // 获取密码类型
          return protocolWorker
              .sendAndGetRsp(
                  (_msgFactory().specialMessageFactory as V12MessageFactory)
                      .genRequestPasswordTypeMsg())
              .then((rspMsg) {
            v12settings.passwordType = ByteUtil.toUint4(
                (rspMsg.data as LorinSpecialMessageData).para![0]);
            // 获取显示屏设备名
            return protocolWorker
                .sendAndGetRsp(
                    (_msgFactory().specialMessageFactory as V12MessageFactory)
                        .genRequestDeviceNameMsg())
                .then((rspMsg) {
              try {
                v12settings.deviceName = ByteUtil.bytes2String(
                    (rspMsg.data as LorinSpecialMessageData).para!).replaceAll(RegExp('\x00'), '').trim();
              } catch (e) {
                LogUtils.e('An error occurred when parse device name.', e);
                v12settings.deviceName = "";
              }
              return v12settings;
            });
          });
        });
      });
    });
  }
}

class V13Composer extends LorinComposer {
  V13Composer(ProtocolWorker<LorinMessage> protocolWorker,
      MsgFactory msgFactory, ProductProperty property, Parser parser)
      : super(protocolWorker, msgFactory, property, parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      V13Settings v13settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as V13Settings;
      // 获取密码类型
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as V13MessageFactory)
                  .genRequestPasswordTypeMsg())
          .then((rspMsg) {
        v13settings.passwordType =
            ByteUtil.toUint4((rspMsg.data as LorinSpecialMessageData).para![0]);
        // 获取显示屏设备名
        return protocolWorker
            .sendAndGetRsp(
                (_msgFactory().specialMessageFactory as V13MessageFactory)
                    .genRequestDeviceNameMsg())
            .then((rspMsg) {
          try {
            v13settings.deviceName = ByteUtil.bytes2String(
                (rspMsg.data as LorinSpecialMessageData).para!).replaceAll(RegExp('\x00'), '').trim();
          } catch (e) {
            LogUtils.e('An error occurred when parse device name.', e);
            v13settings.deviceName = "";
          }
          return v13settings;
        });
      });
    });
  }
}

class V14Composer extends LorinComposer {
  V14Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);
}

class V18Composer extends LorinComposer {
  V18Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      V18Settings v18settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as V18Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as V18MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        v18settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (v18settings.lightEffectMode.value ==
            V18Settings.lightEffectModeByMusic) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          v18settings.colorOfLightEffectByMusic = color;
        } else if (v18settings.lightEffectMode.value ==
            V18Settings.lightEffectModeBySpeed) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          v18settings.colorOfLightEffectBySpeed = color;
        } else if (v18settings.lightEffectMode.value ==
            V18Settings.lightEffectModeAlwaysOn) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          v18settings.colorOfLightEffectByAlwaysOn = color;
        }
        // 获取密码类型
        return protocolWorker
            .sendAndGetRsp(
                (_msgFactory().specialMessageFactory as V18MessageFactory)
                    .genRequestPasswordTypeMsg())
            .then((rspMsg) {
          v18settings.passwordType = ByteUtil.toUint4(
              (rspMsg.data as LorinSpecialMessageData).para![0]);
          // 获取显示屏设备名
          return protocolWorker
              .sendAndGetRsp(
                  (_msgFactory().specialMessageFactory as V18MessageFactory)
                      .genRequestDeviceNameMsg())
              .then((rspMsg) {
            try {
              v18settings.deviceName = ByteUtil.bytes2String(
                  (rspMsg.data as LorinSpecialMessageData).para!).replaceAll(RegExp('\x00'), '').trim();
            } catch (e) {
              LogUtils.e('An error occurred when parse device name.', e);
              v18settings.deviceName = "";
            }
            return v18settings;
          });
        });
      });
    });
  }
}

class E20Composer extends LorinComposer {
  E20Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      E20Settings e20settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as E20Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as E20MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        e20settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (e20settings.lightEffectMode.value ==
            E20Settings.lightEffectModeBySpeed) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e20settings.colorOfLightEffectBySpeed = color;
        } else if (e20settings.lightEffectMode.value ==
            E20Settings.lightEffectModeAlwaysOn) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e20settings.colorOfLightEffectAlwaysOn = color;
        }
        return e20settings;
      });
    });
  }
}

class E10Composer extends LorinComposer {
  E10Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      E10Settings e10settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as E10Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as E10MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        e10settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (e10settings.lightEffectMode.value ==
            E10Settings.lightEffectModeBySpeed) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e10settings.colorOfLightEffectBySpeed = color;
        } else if (e10settings.lightEffectMode.value ==
            E10Settings.lightEffectModeAlwaysOn) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e10settings.colorOfLightEffectAlwaysOn = color;
        }
        return e10settings;
      });
    });
  }
}

class P6Composer extends LorinComposer {
  P6Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      P6Settings p6settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as P6Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as P6MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        p6settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (p6settings.lightEffectMode.value ==
            P6Settings.lightEffectModeByMusic) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          p6settings.colorOfLightEffectByMusic = color;
        } else if (p6settings.lightEffectMode.value ==
            P6Settings.lightEffectModeBySpeed) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          p6settings.colorOfLightEffectBySpeed = color;
        } else if (p6settings.lightEffectMode.value ==
            P6Settings.lightEffectModeAlwaysOn) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          p6settings.colorOfLightEffectByAlwaysOn = color;
        }
        // 获取密码类型
        return protocolWorker
            .sendAndGetRsp(
                (_msgFactory().specialMessageFactory as P6MessageFactory)
                    .genRequestPasswordTypeMsg())
            .then((rspMsg) {
          p6settings.passwordType = ByteUtil.toUint4(
              (rspMsg.data as LorinSpecialMessageData).para![0]);
          // 获取显示屏设备名
          return protocolWorker
              .sendAndGetRsp(
                  (_msgFactory().specialMessageFactory as P6MessageFactory)
                      .genRequestDeviceNameMsg())
              .then((rspMsg) {
            try {
              p6settings.deviceName = ByteUtil.bytes2String(
                  (rspMsg.data as LorinSpecialMessageData).para!).replaceAll(RegExp('\x00'), '').trim();
            } catch (e) {
              LogUtils.e('An error occurred when parse device name.', e);
              p6settings.deviceName = "";
            }
            return p6settings;
          });
        });
      });
    });
  }
}

class V6Composer extends LorinComposer {
  V6Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      V6Settings v6settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as V6Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as V6MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        v6settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (v6settings.lightEffectMode.value ==
            V6Settings.lightEffectModeBySpeed) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          v6settings.colorOfLightEffectBySpeed = color;
        } else if (v6settings.lightEffectMode.value ==
            V6Settings.lightEffectModeAlwaysOn) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          v6settings.colorOfLightEffectAlwaysOn = color;
        }
        return v6settings;
      });
    });
  }
}

class E25Composer extends LorinComposer {
  E25Composer(
      super.protocolWorker, super.msgFactory, super.property, super.parser);

  @override
  Future<Settings> requestSettings() {
    return protocolWorker
        .sendAndGetRsp(_msgFactory().genRequestSettingsMsg())
        .then((rspMsg) {
      E25Settings e25settings =
          _parser.parseSettings((rspMsg.data as LorinSpecialMessageData).para!)
              as E25Settings;

      // 获取灯效信息
      return protocolWorker
          .sendAndGetRsp(
              (_msgFactory().specialMessageFactory as E25MessageFactory)
                  .genRequestLightEffectMsg())
          .then((rspMsg) {
        Uint8ClampedList param = (rspMsg.data as LorinSpecialMessageData).para!;
        e25settings.lightEffectMode = ByteUtil.toUint8(param[0]);

        if (e25settings.lightEffectMode.value ==
            E25Settings.lightEffectModeByMusic) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e25settings.colorOfLightEffectByMusic = color;
        } else if (e25settings.lightEffectMode.value ==
            E25Settings.lightEffectModeBySpeed) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e25settings.colorOfLightEffectBySpeed = color;
        } else if (e25settings.lightEffectMode.value ==
            E25Settings.lightEffectModeAlwaysOn) {
          Uint32 color = ByteUtil.bytes2Uint24(param, 1);
          e25settings.colorOfLightEffectByAlwaysOn = color;
        }
        return e25settings;
      });
    });
  }
}

class InitException implements Exception {
  final String _msg;

  InitException(this._msg);

  @override
  String toString() {
    return _msg;
  }
}
